package com.putable.nmc.world;

import java.io.IOException;
import java.io.Writer;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.InputMismatchException;
import java.util.Map;
import java.util.Scanner;

public enum CustomerType { 
    STUDENT(0.00), BIKER(0.10), WORKER(0.25), RETIREE(0.80);
    private final double complainProbability;
    private int willWait;
    private int sumWeight;
    private static class TaskInfo {
        int weight;
        int time;
        public TaskInfo(int weight, int time) {
            this.weight = weight;
            this.time = time;
        }
    };
    private CustomerType(double prob) { complainProbability = prob; }
    
    private Map<Task,TaskInfo> info = new EnumMap<Task,TaskInfo>(Task.class);

    Task pickTask(XRandom r) {
        int pick = r.nextInt(sumWeight);
        Task ret = null;
        for (Task t : info.keySet()) {
            TaskInfo ti = info.get(t);
            pick -= ti.weight;
            if (pick <= 0) {
                ret = t;
                break;
            }
        }
        if (ret == null)
            throw new IllegalStateException("No task picked?");
        return ret;
    }

    double getComplainProbability() { return this.complainProbability; }
    
    double getTaskTime(XRandom r, Task t) {
        TaskInfo ti = info.get(t);
        return r.nextExponential(ti.time);
    }
    double getWaitTime(XRandom r) {
        return r.nextExponential(willWait);
    }

    static void readInfo(Scanner sc) throws InputMismatchException {
        for (CustomerType ct : EnumSet.allOf(CustomerType.class)) {
            ct.willWait = sc.nextInt();
            ct.sumWeight = 0;
            for (Task t : EnumSet.allOf(Task.class)) {
                int weight = sc.nextInt();
                if (weight < 0)
                    throw new InputMismatchException("Bad weight");

                int time = sc.nextInt();
                if (time <= 0)
                    throw new InputMismatchException("Bad average task time");

                ct.sumWeight += weight;
                ct.info.put(t,new TaskInfo(weight,time));
            }
            sc.nextLine();  // eat rest of line
        }
    }
    static void saveInfo(Writer w) throws IOException {
        for (CustomerType ct : EnumSet.allOf(CustomerType.class)) {
            w.write(""+ct.willWait);
            for (Task t : EnumSet.allOf(Task.class)) {
                TaskInfo ti = ct.info.get(t);
                w.write(" "+ti.weight);
                w.write(" "+ti.time);
            }
            w.write("\t"+ct+" wait (weight time)*tasks\n");
        }
        
    }
}
